package com.iisigroup.audf.statistics;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import net.sf.jxls.exception.ParsePropertyException;
import net.sf.jxls.transformer.XLSTransformer;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Workbook;
import org.robert.study.utils.POIUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.iisigroup.audf.model.Context;
import com.iisigroup.audf.model.ExecelSheet;
import com.iisigroup.project.statistics.Scan001;

public class Phase2Analyzer {
    private static Logger logger = LoggerFactory.getLogger(Phase2Analyzer.class);
    class Unit {
	private String taskcode;
	private String spendMinute;
	private String txId;
	public String getTaskcode() {
	    return taskcode;
	}
	public void setTaskcode(String taskcode) {
	    this.taskcode = taskcode;
	}
	public String getSpendMinute() {
	    return spendMinute;
	}
	public void setSpendMinute(String spendMinute) {
	    this.spendMinute = spendMinute;
	}
	public String getTxId() {
	    return txId;
	}
	public void setTxId(String txId) {
	    this.txId = txId;
	}
	
    }
    public List<ExecelSheet> processAudf1000UnitCore(final File srcFile ,final Map<String, String> chtNameMap) throws IOException{
	final List<ExecelSheet> resultList = new ArrayList<ExecelSheet>();
	final	SimpleDateFormat sdf  =new SimpleDateFormat("mm:ss.SSS");
	final	List<String> lines = FileUtils.readLines(srcFile);
	Map<String,List<Unit>> initMap = new HashMap<String,List<Unit>>();
	for(String line : lines ){
	    if(StringUtils.contains(line, "|")){
		String[] str = StringUtils.splitPreserveAllTokens(line,"|");
		String taskCode = StringUtils.trim(str[1]);
		Unit unit = new Unit();	
		unit.setTxId(StringUtils.trim(str[0]));
		unit.setTaskcode(taskCode);
		unit.setSpendMinute(StringUtils.trim(str[2]));
		List<Unit> list = initMap.get(taskCode);
		if(list == null){
		    list = new ArrayList<Phase2Analyzer.Unit>();
		}
		list.add(unit);
		initMap.put(taskCode, list);
	    }
	}
	for(String taskCode  : initMap.keySet()){
	    List<Unit> list = initMap.get(taskCode);
	   
	    final List<Long> valueList  =new ArrayList<Long>();
	    //平均值計算
	    for(Unit unit : list){
		String time = unit.getSpendMinute();
		try {
		    Long vlaue = Long.valueOf(sdf.parse(time).getTime());
		    valueList.add(vlaue);
		} catch (ParseException e) {
		    e.printStackTrace();
		}
	    }
	  //取樣次數
	    int sampleNo = valueList.size();	
	    long[] vlaueArray =  new long[sampleNo];
	    long total = 0; 
	    for(int i = 0 ;i<valueList.size() ;++i){
		vlaueArray[i] = valueList.get(i);
		total = total + valueList.get(i);
	    }
	   //最小值
	   long minValue = NumberUtils.min(vlaueArray);
	   String minimium = sdf.format(new Date(minValue));
	   
	   //最大值
	   long maxValue = NumberUtils.max(vlaueArray);
	   String maximium = sdf.format(new Date(maxValue));
	  
	   //平均值
	   long averageValue =  total/((long)sampleNo);
	   String average = sdf.format(new Date(averageValue));
	   
	   //標準差
	   double std = Deviation.calculate(vlaueArray);
	   
	   long stdl = (long) std;
	   String stdDeviation = sdf.format(new Date(stdl));
	   
	   //90百分位計算
	   
	   //移除的數量
//	   BigDecimal initData =new BigDecimal(sampleNo).multiply(new BigDecimal(0.9d)).divide(new BigDecimal(2));
	   BigDecimal initData =new BigDecimal(sampleNo).multiply(new BigDecimal(0.9d));
	   
	   //最高峰...與最低谷移除量
	   int removeNo =initData.intValue();
	   Collections.sort(valueList);
	   int count =0;
	   long total90 =0l;
//	   for(int i = removeNo ;i<(valueList.size()- removeNo); ++ i ){
//	      Long element = valueList.get(i);
//	      total90  = total90 +element.longValue();
//	      count++;
//	   }
	    for (int i = 0; i < (valueList.size() - removeNo); ++i) {
		Long element = valueList.get(i);
		total90 = total90 + element.longValue();
		count++;
	    }
	   String calculate90 = sdf.format(new Date(total90/(long)count));
	   String tempalte ="作業名稱:%s ,取樣次數:%s ,平均值:%s ,90百分位:%s ,最大值:%s ,最小值:%s ,標準差:%s";
	   String line  = String.format(tempalte, taskCode,sampleNo,average,calculate90,maximium,minimium,stdDeviation);
	   System.out.println(line);
	   String fileName = srcFile.getName();
	   String appenddata =  "0:";
	   String finalTaskName = StringUtils.EMPTY;
	   if(StringUtils.contains(taskCode, "_")){
	      final String[] taskArray = StringUtils.splitPreserveAllTokens(taskCode, "_");
	      final String[] taskChtArray= new String[taskArray.length];
	      for(int i= 0 ;i<taskArray.length;++i){
		  String task =  taskArray[i];
		  taskChtArray[i] = chtNameMap.get(task);		 
	      }
	      finalTaskName = taskCode +"("+ StringUtils.join(taskChtArray,"_") +")";
	     ;
	   }
	   
//	   final ExecelSheet unitData = new ExecelSheet(fileName, finalTaskName,String.valueOf(sampleNo),appenddata+average,appenddata+calculate90,appenddata+maximium,appenddata+minimium,appenddata+stdDeviation);
	   final ExecelSheet unitData = new ExecelSheet(fileName, taskCode,String.valueOf(sampleNo),appenddata+average,appenddata+calculate90,appenddata+maximium,appenddata+minimium,appenddata+stdDeviation);
	   resultList.add(unitData);
	}
	final Comparator<ExecelSheet> comparator=new Comparator<ExecelSheet>(){
	    public int compare(ExecelSheet o1, ExecelSheet o2) {
		return 	o1.getTaskName().compareTo(o2.getTaskName());
	    }} ;
	
	Collections.sort(resultList ,comparator);
	return resultList;
    }
    public void processAudf1000UnitV1(final File srcFile ) throws IOException{
	final	Map<String, String> chtNameMap = geChtNameMap();
	final List<ExecelSheet> resultList = processAudf1000UnitCore(srcFile, chtNameMap);
	
	Map<String, Object> beans = new HashMap<String, Object>();
	Context data = new Context();
	data.setLine(resultList);
	beans.put("data", data);
	XLSTransformer transformer = new XLSTransformer();
	try {
	    final    InputStream stream = Phase2Analyzer.class.getResource("template.xls").openStream();
	    final    Workbook aHSSFWorkbook = transformer.transformXLS(stream, beans);
	    final   File dir = new File(srcFile.getParent()+"/output/"); 
	    if(!dir.exists()){
		FileUtils.forceMkdir(dir);
	    }
	    final   String fileName =    srcFile.getParent()+"/output/"+ srcFile.getName()+"_output.xls";
	    POIUtils.writeWorkbookOut(new File(fileName), aHSSFWorkbook);
	    System.out.println("output file path: "+fileName);
	} catch (ParsePropertyException | InvalidFormatException e) {
	    e.printStackTrace();
	}
    }

    public void processAudf1000UnitV2(final File... srcFiles) throws IOException {
	final	SimpleDateFormat sdf  =new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
	String dirPath= StringUtils.EMPTY;
	final Map<String, String> chtNameMap = geChtNameMap();
	final Set<String> rowFuncTaskSet = new HashSet<String>();
	final Map<String,Map<String ,ExecelSheet>> dataMap = new HashMap<String,Map<String ,ExecelSheet>>();
	for (File unitFile : srcFiles) {
	    if(unitFile.isDirectory()){
		continue;
	    }
	    dirPath = unitFile.getParent() + "/output/";
	    List<ExecelSheet> resultList = processAudf1000UnitCore(unitFile, chtNameMap);
	    Map<String ,ExecelSheet> unitMap =new HashMap<String ,ExecelSheet>();
	    for(ExecelSheet unitExecelSheet: resultList){
		rowFuncTaskSet.add(unitExecelSheet.getTaskName());
		unitMap.put(unitExecelSheet.getTaskName(), unitExecelSheet);
	    }
	    dataMap.put(unitFile.getName(), unitMap);
	    
	}
	// TODO
	Map<String, Object> beans = new HashMap<String, Object>();
	Context data = new Context();
	data.setDataMap(dataMap);
	data.getRowFuncTaskSet().addAll(rowFuncTaskSet);
	beans.put("data", data);
//	inspect(dataMap);
	XLSTransformer transformer = new XLSTransformer();
	try {
	    final InputStream stream = Phase2Analyzer.class.getResource("template2.xls").openStream();
	    final Workbook aHSSFWorkbook = transformer.transformXLS(stream, beans);
	    final File dir = new File(dirPath);
	    if (!dir.exists()) {
		FileUtils.forceMkdir(dir);
	    }
	    final String fileName = dirPath+ "/total" + sdf.format(new Date()) + "_output.xls";
	    POIUtils.writeWorkbookOut(new File(fileName), aHSSFWorkbook);
	    System.out.println("output file path: " + fileName);
	} catch (ParsePropertyException | InvalidFormatException e) {
	    e.printStackTrace();
	}
    }
    private void inspect(Map<String, Map<String, ExecelSheet>> dataMap) {
	for(String siteId: dataMap.keySet()){
	    System.out.println(siteId);
	    final Map<String, ExecelSheet> dddmap = dataMap.get(siteId);
	    for(String taskCode: dddmap.keySet()){
		System.out.println(taskCode+"___"+siteId);
		ExecelSheet exec = dddmap.get(taskCode);
		System.out.println("Average: "+ exec.getAverage());
		System.out.println("std: "+ exec.getStD());
		System.out.println("-----------");
	    }
	}
	
    }
    private Map<String, String> geChtNameMap() {
  	Properties props = new Properties();
  	try {
  	    props.load(Scan001.class.getResourceAsStream("RLCDTKLST.properties"));
  	} catch (Exception e) {
  	    e.printStackTrace();
  	}
  	final Set<Object> keys = props.keySet();
  	final Map<String, String> siteIdMap = new HashMap<String, String>();
  	for (Object key : keys) {
  	    Object value = props.get(key);
  	    siteIdMap.put(key.toString(), value.toString());
  	}
  	return siteIdMap;
    }
}

